<audio id="audio_wave" src="../data/deleuze/01_10-02-81_9A.ogg" controls>
</audio>

<canvas id="canvas_wave" width="512" height="200">
</canvas>
<div><canvas id="fft" width="512" height="200"></canvas></div>
<div id="txt_wave" >
</div>

<script type="text/javascript" >
  var audio = document.getElementById("audio_wave");
  var canvas = document.getElementById("canvas_wave");
  var txt = document.getElementById("txt_wave"), sec=-1;
  var fbLength, channels, rate, fft;
  var context = canvas.getContext('2d');
  context.strokeStyle = "#FFFFFF";
  context.lineWidth = 2;
  var cnv = document.getElementById('fft'),
  ctx = cnv.getContext('2d');
    
  audio.addEventListener("loadedmetadata", getMetadata, false);
  audio.addEventListener("MozAudioAvailable", writeSamples, false);
  
  	function getMetadata() {
    	channels		= audio.mozChannels;
    	fbLength 		= audio.mozFrameBufferLength;
		rate			= audio.mozSampleRate;
		fft 			= new FFT(fbLength / channels, rate);
  	}  

	  // Render the waveform
	  function writeSamples (event){
	    var data = event.frameBuffer
	    ,samples = 512
	    ,step = (fbLength / channels) / samples
        ,t  = event.time
        ,signal = new Float32Array(data.length / channels)
        ,magnitude, maxMag = 0;

		for (var i = 0, fbl = fbLength / 2; i < fbl; i++ ) {
	        // Assuming interlaced stereo channels,
	        // need to split and merge into a stero-mix mono signal
			signal[i] = (data[2*i] + data[2*i+1]) / 2;
		}
        
		// Clear the canvas before drawing spectrum
        ctx.clearRect(0,0, cnv.width, cnv.height);
        	    
	    fft.forward(signal);
	    for (var i = 0; i < fft.spectrum.length; i++ ) {
			// multiply spectrum by a zoom value
		    magnitude = fft.spectrum[i] * 4000;
			// Draw rectangle bars for each frequency bin
	        ctx.fillRect(i * 4, canvas.height, 3, -magnitude);
			//calcul la plus grande magnitude
	        if(maxMag < magnitude) maxMag = magnitude;		    
		}
		//conserve la plus grande magnitude pour une seconde
		if(sec!=Math.round(t)){
		    txt.innerHTML +=  Math.round(t)+","+(Math.round(maxMag*100))/100+"<br/>";
		    sec=Math.round(t);
		}	
	    
	    context.fillRect(0, 0, 512, 200);
	    context.beginPath();
	    context.moveTo(0, 100-data[0]*100);
	    for(var i=1; i < samples; i++){
	      context.lineTo(i, 100-data[i*step]*100);
	    }
	    context.stroke();
	  }  

	  // FFT from dsp.js, see below
	  var FFT = function(bufferSize, sampleRate) {
	    this.bufferSize   = bufferSize;
	    this.sampleRate   = sampleRate;
	    this.spectrum     = new Float32Array(bufferSize/2);
	    this.real         = new Float32Array(bufferSize);
	    this.imag         = new Float32Array(bufferSize);
	    this.reverseTable = new Uint32Array(bufferSize);
	    this.sinTable     = new Float32Array(bufferSize);
	    this.cosTable     = new Float32Array(bufferSize);
	
	    var limit = 1,
	        bit = bufferSize >> 1;
	
	    while ( limit < bufferSize ) {
	      for ( var i = 0; i < limit; i++ ) {
	        this.reverseTable[i + limit] = this.reverseTable[i] + bit;
	      }
	
	      limit = limit << 1;
	      bit = bit >> 1;
	    }
	
	    for ( var i = 0; i < bufferSize; i++ ) {
	      this.sinTable[i] = Math.sin(-Math.PI/i);
	      this.cosTable[i] = Math.cos(-Math.PI/i);
	    }
	  };

	  FFT.prototype.forward = function(buffer) {
	    var bufferSize   = this.bufferSize,
	        cosTable     = this.cosTable,
	        sinTable     = this.sinTable,
	        reverseTable = this.reverseTable,
	        real         = this.real,
	        imag         = this.imag,
	        spectrum     = this.spectrum;
	
	    if ( bufferSize !== buffer.length ) {
	      throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length;
	    }
	
	    for ( var i = 0; i < bufferSize; i++ ) {
	      real[i] = buffer[reverseTable[i]];
	      imag[i] = 0;
	    }
	
	    var halfSize = 1,
	        phaseShiftStepReal,	
	        phaseShiftStepImag,
	        currentPhaseShiftReal,
	        currentPhaseShiftImag,
	        off,
	        tr,
	        ti,
	        tmpReal,	
	        i;
	
	    while ( halfSize < bufferSize ) {
	      phaseShiftStepReal = cosTable[halfSize];
	      phaseShiftStepImag = sinTable[halfSize];
	      currentPhaseShiftReal = 1.0;
	      currentPhaseShiftImag = 0.0;
	
	      for ( var fftStep = 0; fftStep < halfSize; fftStep++ ) {
	        i = fftStep;
	
	        while ( i < bufferSize ) {
	          off = i + halfSize;
	          tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
	          ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
	
	          real[off] = real[i] - tr;
	          imag[off] = imag[i] - ti;
	          real[i] += tr;
	          imag[i] += ti;
	
	          i += halfSize << 1;
	        }
	
	        tmpReal = currentPhaseShiftReal;
	        currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
	        currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
	      }
	
	      halfSize = halfSize << 1;
	}
	
	    i = bufferSize/2;
	    while(i--) {
	      spectrum[i] = 2 * Math.sqrt(real[i] * real[i] + imag[i] * imag[i]) / bufferSize;
	}
  };
    
</script>    